home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCFSRC.PAK / TYPELIB.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  25KB  |  756 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1997 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.15  $
  6. //
  7. // TServedObject implementation and OLE Type library generation
  8. //----------------------------------------------------------------------------
  9. #include <ocf/pch.h>
  10. #if !defined(OCF_APPDESC_H)
  11. # include <ocf/appdesc.h>
  12. #endif
  13. #if !defined(SERVICES_MEMORY_H)
  14. # include <services/memory.h>
  15. #endif
  16. #if !defined(OCF_OCCTRL_H) && defined(BI_PLAT_WIN32)
  17. # include <ocf/occtrl.h>
  18. #endif
  19.  
  20. #if defined(BI_PLAT_WIN32)
  21. # define OLE_TYPELIB_FILE L"stdole32.tlb"
  22. #elif defined(BI_PLAT_WIN16)
  23. # define OLE_TYPELIB_FILE "stdole.tlb"
  24. #endif
  25.  
  26. //____________________________________________________________________________
  27. //
  28. // TypeLibrary generation
  29. //____________________________________________________________________________
  30.  
  31. // local class to hold ICreateTypeLib interface pointers for each class
  32.  
  33. struct TOleCreateInfo {
  34.   int FuncCount;
  35.   int VarCount;
  36.   int ImplCount;
  37.   TYPEKIND TypeKind;
  38.   ITypeInfo*       OurTypeInfo;  // our type info implementation
  39.   ITypeInfo*       OleTypeInfo;  // type info obtained from ICreatTypeInfo
  40.   ICreateTypeInfo* CreateInfo;   // interface obtained from ICreateTypeLib
  41.   TOleCreateInfo() : OurTypeInfo(0), OleTypeInfo(0), CreateInfo(0) {}
  42.  ~TOleCreateInfo();
  43. };
  44.  
  45. TOleCreateInfo::~TOleCreateInfo()
  46. {
  47.   if (OurTypeInfo)
  48.     OurTypeInfo->Release();
  49.   if (OleTypeInfo)
  50.     OleTypeInfo->Release();
  51.   if (CreateInfo)
  52.     CreateInfo->Release();
  53. }
  54.  
  55. struct TOleCreateList {
  56.   int             Count;
  57.   ITypeLib*       TypeLib;
  58.   const char far* FileName;
  59.   TOleCreateInfo* List;
  60.   ITypeLib*       OleLib;
  61.   ITypeComp*      OleComp;
  62.   ITypeInfo*      OleInfo;
  63.   ICreateTypeLib* CreateLib;
  64.   TLIBATTR far*   LibAttr;
  65.   TYPEATTR far*   TypeAttr;
  66.   ITypeInfo*      AttrTypeInfo;  // valid only when TypeAttr!=0, not refcnt'd
  67.   TBSTR* FuncNames;              // temporary transfer of BSTR name arrays
  68.  
  69.   TOleCreateList(ITypeLib* typeLib, const char far* fileName);
  70.   void FixupTypeDescRef(int typeIndex, TYPEDESC far& typeDesc);
  71.   void Close(const char far* helpDir);
  72.   void Clear();
  73.  ~TOleCreateList() {Clear();}
  74. };
  75.  
  76. TOleCreateList::TOleCreateList(ITypeLib* typeLib, const char far* fileName)
  77. :
  78.   TypeLib(typeLib),
  79.   FileName(fileName),
  80.   OleLib(0), OleComp(0), OleInfo(0),
  81.   CreateLib(0), TypeAttr(0), LibAttr(0), List(0), FuncNames(0)
  82. {
  83.   TBSTR libName;
  84.   TBSTR libDoc;
  85.   TBSTR helpFile;
  86.   ulong helpId;
  87.   TypeLib->AddRef();
  88.   OLECALL(::LoadTypeLib(OLE_TYPELIB_FILE, &OleLib), "Load stdole.tlb");
  89.   OLECALL(OleLib->GetTypeComp(&OleComp), "GetTypeComp");
  90.   ITypeComp* tempComp;     // required as reference arg, but always set to 0
  91.   OLECALL(OleComp->BindType(OleText("IDispatch"),
  92.                             ::LHashValOfName(0, OleText("IDispatch")),
  93.                             &OleInfo,&tempComp), "BindType");
  94.   OLECALL(TypeLib->GetLibAttr(&LibAttr), "GetLibAttr");
  95.   OLECALL(TypeLib->GetDocumentation(-1, libName, libDoc, &helpId, helpFile),
  96.                                          "GetDocumentation for library");
  97.   OLECALL(::CreateTypeLib(LibAttr->syskind, OleStr((char far*)FileName), &CreateLib), "CreateTypeLib");
  98.   OLECALL(CreateLib->SetGuid(LibAttr->guid), "Set TypeLib GUID");
  99.   OLECALL(CreateLib->SetLcid(LibAttr->lcid), "Set TypeLib language");
  100.   OLECALL(CreateLib->SetLibFlags(LibAttr->wLibFlags), "Set TypeLib flags");
  101.   if (!!libName)
  102.     OLECALL(CreateLib->SetName(libName), "Set TypeLib name");
  103.   if (!!libDoc)
  104.     OLECALL(CreateLib->SetDocString(libDoc), "Set TypeLib doc");
  105.   if (!!helpFile)
  106.   {
  107.     OLECALL(CreateLib->SetHelpFileName(helpFile), "SetHelpFileName");
  108.     OLECALL(CreateLib->SetHelpContext(helpId), "HelpContext");
  109.   }
  110.   OLECALL(CreateLib->SetVersion(LibAttr->wMajorVerNum,
  111.                                 LibAttr->wMinorVerNum), "Set TypeLib version");
  112.   //  allocate all ITypeInfo's upfront to force consistent references
  113.   Count = TypeLib->GetTypeInfoCount();
  114.   List = new TOleCreateInfo[Count];
  115.   for (int nInfo = 0; nInfo < Count; nInfo++) {
  116.     TOleCreateInfo& info = List[nInfo];
  117.     ICreateTypeInfo* newInfo;
  118.     OLECALL(TypeLib->GetTypeInfo(nInfo, &AttrTypeInfo), "GetTypeInfo");
  119.     info.OurTypeInfo = AttrTypeInfo;
  120.     OLECALL(info.OurTypeInfo->GetTypeAttr(&TypeAttr), "GetTypeAttr");
  121.     OLECALL(TypeLib->GetDocumentation(nInfo,libName,libDoc,&helpId,helpFile),
  122.                                              "GetDocumentation for TypeInfo");
  123.     OLECALL(CreateLib->CreateTypeInfo(libName, TypeAttr->typekind, &newInfo),
  124.                                    "Create CreateTypeInfo");
  125.     info.CreateInfo = newInfo;
  126.     OLECALL(newInfo->QueryInterface(IID_ITypeInfo,
  127.            (void far*far*)&info.OleTypeInfo), "QueryInterface for ITypeInfo");
  128.     if (!!libDoc)
  129.       OLECALL(newInfo->SetDocString(libDoc), "Set TypeInfo doc");
  130.     OLECALL(newInfo->SetHelpContext(helpId), "SetHelpContext");
  131.     OLECALL(newInfo->SetVersion(TypeAttr->wMajorVerNum,
  132.                                   TypeAttr->wMinorVerNum),"Set TypeInfo version");
  133.     OLECALL(newInfo->SetGuid(TypeAttr->guid), "SetTypeInfo GUID");
  134.     OLECALL(newInfo->SetTypeFlags(TypeAttr->wTypeFlags), "SetTypeFlags");
  135.     if (TypeAttr->typekind == TKIND_DISPATCH) {
  136.       HREFTYPE hreftype;
  137.       OLECALL(newInfo->AddRefTypeInfo(OleInfo, &hreftype), "AddRefTypeInfo");
  138.       OLECALL(newInfo->AddImplType(0, hreftype), "AddImplType");
  139.     }
  140.     info.TypeKind  = TypeAttr->typekind;
  141.     info.FuncCount = TypeAttr->cFuncs;
  142.     info.VarCount  = TypeAttr->cVars;
  143.     info.ImplCount = TypeAttr->cImplTypes;
  144.     info.OurTypeInfo->ReleaseTypeAttr(TypeAttr), TypeAttr = 0;
  145.   }
  146. }
  147.  
  148. void TOleCreateList::Close(const char far* helpDir)
  149. {
  150.   OLECALL(CreateLib->SaveAllChanges(), "Write and close TypeLib file");
  151.   CreateLib->Release();
  152.   CreateLib = 0;
  153.   OLECALL(::RegisterTypeLib(TypeLib,
  154.                             OleStr((char far*)FileName),
  155.                             OleStr((char far*)helpDir)),
  156.           "Register type library");
  157. }
  158.  
  159. void TOleCreateList::Clear()
  160. {
  161.   delete[] List;  // releases all interface pointers
  162.   delete[] FuncNames;  // in case exception thrown while in use
  163.   if (LibAttr)
  164.     TypeLib->ReleaseTLibAttr(LibAttr);
  165.   if (TypeAttr)
  166.     AttrTypeInfo->ReleaseTypeAttr(TypeAttr);
  167.   if (OleInfo)
  168.     OleInfo->Release();
  169.   if (OleComp)
  170.     OleComp->Release();
  171.   if (OleLib)
  172.     OleLib->Release();
  173.   if (CreateLib)
  174.     CreateLib->Release();
  175.   TypeLib->Release();  // finally release typelib called at constructor
  176. }
  177.  
  178. void
  179. TOleCreateList::FixupTypeDescRef(int typeIndex, TYPEDESC far& typeDesc)
  180. {
  181.   if (typeDesc.vt == VT_USERDEFINED) {
  182.     ITypeInfo* refInfo;
  183.     OLECALL(List[typeIndex].OurTypeInfo->GetRefTypeInfo(typeDesc.hreftype,
  184.                                                  &refInfo), "GetRefTypeInfo");
  185.     refInfo->Release();   // ok to release here, we're only using its pointer
  186.     for (int nInfo = 0; nInfo < Count; nInfo++) {
  187.        if (List[nInfo].OurTypeInfo == refInfo) {
  188.          OLECALL(List[typeIndex].CreateInfo->AddRefTypeInfo(List[nInfo].OleTypeInfo,
  189.                                        &typeDesc.hreftype), "AddRefTypeInfo");
  190.          return;
  191.        }
  192.     }
  193.     OLECALL(HR_TYPE_ELEMENTNOTFOUND, "Unknown reference type");
  194.   }
  195. }
  196.  
  197. void
  198. TAppDescriptor::WriteTypeLibrary(TLangId lang, const char far* file)
  199. {
  200.   TServedObject* servedObject;
  201.   TBSTR libName;
  202.   TBSTR libDoc;
  203.   ulong helpId;
  204.   FUNCDESC far* funcDesc = 0;
  205.   VARDESC far* varDesc = 0;
  206.   TOleCreateList typeList(new TTypeLibrary(*this, lang), file);
  207.   for (int nInfo = 0; nInfo < typeList.Count; nInfo++) {
  208.     TOleCreateInfo& curInfo = typeList.List[nInfo];
  209.     ITypeInfo* typeInfo = curInfo.OurTypeInfo;
  210.     ICreateTypeInfo* newInfo  = curInfo.CreateInfo;
  211.     int index;
  212.     for (index = 0; index < curInfo.FuncCount; index++) {
  213.       OLECALL(typeInfo->GetFuncDesc(index, &funcDesc), "GetFuncDesc");
  214.       // Using the GetDocumentation call fails when creating a typelib, so attempt to
  215.       // use the function GetFuncDocFromIndex to get around this problem
  216.       servedObject = dynamic_cast<TServedObject*>(typeInfo);
  217.       if (servedObject)
  218.         OLECALL(servedObject->GetFuncDocFromIndex(index, libName, libDoc,
  219.                                                   &helpId, 0), "Get method name and doc");
  220.       else
  221.         OLECALL(typeInfo->GetDocumentation(funcDesc->memid, libName, libDoc,
  222.                                            &helpId, 0), "Get method name and doc");
  223.       for (int nArg = funcDesc->cParams; nArg-- >=0; ) {
  224.         ELEMDESC far* elem = nArg < 0 ? &funcDesc->elemdescFunc
  225.                                       : &funcDesc->lprgelemdescParam[nArg];
  226.         typeList.FixupTypeDescRef(nInfo, elem->tdesc);
  227.       }
  228.       OLECALL(newInfo->AddFuncDesc(index, funcDesc), "AddFuncDesc");
  229.       unsigned nNames = funcDesc->cParams + 1;
  230.       typeList.FuncNames = new TBSTR[nNames];
  231.       OLECALL(typeInfo->GetNames(funcDesc->memid, (BSTR*)typeList.FuncNames,
  232.                               nNames, &nNames), "Get method parameter names");
  233.       OLECALL(newInfo->SetFuncAndParamNames(index, (BSTR*)typeList.FuncNames,
  234.                                        nNames), "Set method parameter names");
  235.       delete[] typeList.FuncNames;
  236.       typeList.FuncNames = 0;
  237.       if (!!libDoc)
  238.         OLECALL(newInfo->SetFuncDocString(index, libDoc),"Set method doc");
  239.       OLECALL(newInfo->SetFuncHelpContext(index, helpId), "HelpContext");
  240.       typeInfo->ReleaseFuncDesc(funcDesc), funcDesc = 0;
  241.     }
  242.     for (index = 0; index < curInfo.VarCount; index++) {
  243.       OLECALL(typeInfo->GetVarDesc(index, &varDesc), "GetVarDesc");
  244.       // Using the GetDocumentation call fails when creating a typelib, so attempt to
  245.       // use the function GetVarDocFromIndex to get around this problem
  246.       servedObject = dynamic_cast<TServedObject*>(typeInfo);
  247.       if (servedObject)
  248.         OLECALL(servedObject->GetVarDocFromIndex(index, libName, libDoc,
  249.                                                  &helpId, 0), "Get propery name and doc");
  250.       else
  251.         OLECALL(typeInfo->GetDocumentation(varDesc->memid, libName, libDoc,
  252.                                            &helpId, 0), "Get propery name and doc");
  253.       typeList.FixupTypeDescRef(nInfo, varDesc->elemdescVar.tdesc);
  254.       OLECALL(newInfo->AddVarDesc(index, varDesc), "AddVarDesc");
  255.       OLECALL(newInfo->SetVarName(index, libName),"Set property name");
  256.       if (!!libDoc)
  257.         OLECALL(newInfo->SetVarDocString(index, libDoc),"Set property doc");
  258.       OLECALL(newInfo->SetVarHelpContext(index, helpId), "HelpContext");
  259.       typeInfo->ReleaseVarDesc(varDesc), varDesc = 0;
  260.     }
  261.     if (curInfo.TypeKind == TKIND_COCLASS) {
  262.       for (index = 0; index < curInfo.ImplCount; index++) {
  263.         HREFTYPE hreftype;
  264.         ITypeInfo* refInfo;
  265.         OLECALL(typeInfo->GetRefTypeOfImplType(index, &hreftype),"GetCoClassRef");
  266.         OLECALL(typeInfo->GetRefTypeInfo(hreftype, &refInfo), "GetCoClassTypeInfo");
  267.         refInfo->Release();   // ok to release here, only using its pointer
  268.         for (int iInfo = 0; iInfo < typeList.Count; iInfo++) {
  269.           if (typeList.List[iInfo].OurTypeInfo == refInfo) {
  270.             OLECALL(newInfo->AddRefTypeInfo(typeList.List[iInfo].OleTypeInfo, &hreftype), "AddRefTypeInfo");
  271.             OLECALL(newInfo->AddImplType(index, hreftype), "AddImplType");
  272.             int implflags;
  273.             OLECALL(typeInfo->GetImplTypeFlags(index, &implflags), "GetImplTypeFlags");
  274.             OLECALL(newInfo->SetImplTypeFlags(index, implflags), "SetImplTypeFlags");
  275.           }
  276.         }
  277.       }
  278.     }
  279.     OLECALL(newInfo->LayOut(), "Layout typeinfo");
  280.   }
  281.   const char* helpDir = RegInfo.Lookup("helpdir");
  282.   if (!helpDir || *helpDir == 0) {
  283.     char path [_MAX_PATH];
  284.     char drive[_MAX_DRIVE];
  285.     char dir  [_MAX_DIR];
  286.     ::GetModuleFileName(AppInstance, path, sizeof(path));
  287.     _splitpath(path, drive, dir, 0, 0);
  288.     _makepath (path, drive, dir, 0, 0);
  289.     helpDir = path;
  290.   }
  291.   typeList.Close(helpDir);
  292.  
  293.   int iGuid = 0;   // first pass for app, second for debug app if present
  294.   do {
  295.     char buf[80];
  296.     strcpy(buf, "CLSID\\");
  297.     strcat(buf, AppClassId[iGuid]);
  298.     strcat(buf, "\\TypeLib");
  299.     ::RegSetValue(TRegKey::ClassesRoot,buf,REG_SZ, AppClassId[LibGuidOffset], 0);
  300.     iGuid ^= DebugGuidOffset;    // remains 0 if no debug guid assigned
  301.   } while (iGuid);
  302. }
  303.  
  304. //____________________________________________________________________________
  305. //
  306. // TTypeLibrary implementation
  307. //____________________________________________________________________________
  308.  
  309. TTypeLibrary::TTypeLibrary(TAppDescriptor& appDesc, TLangId lang)
  310.                : AppDesc(appDesc), Lang(lang), RefCnt(0)
  311. {
  312.   CoClassFlags = 0;
  313.   CoClassImplCount = 0;
  314.   TAutoClass::TAutoClassRef* ref = AppDesc.ClassList;
  315.   for (int index = 0; index < AppDesc.ClassCount; index++, ref++) {
  316.     TAutoClass* cls = ref->Class;
  317.     int    implFlags = cls->GetImplTypeFlags();
  318.     uint16 typeFlags = cls->GetCoClassFlags();
  319.     if (implFlags != 0 || typeFlags != 0) {
  320.       CoClassImplCount++;
  321.       CoClassFlags |= typeFlags;
  322.     }
  323.   }
  324. }
  325.  
  326. TTypeLibrary::~TTypeLibrary()
  327. {
  328.   if (AppDesc.TypeLib == this)
  329.     AppDesc.TypeLib = 0;    // remove pointer to this
  330.   if (RefCnt > 0)
  331.     ::CoDisconnectObject(this,0);   // should not normally happen
  332. }
  333.  
  334. ITypeInfo*
  335. TTypeLibrary::CreateCoClassInfo()
  336. {
  337.   ITypeInfo* ifc = new TCoClassInfo(AppDesc, CoClassFlags, CoClassImplCount);
  338.   ifc->AddRef();
  339.   return ifc;
  340. }
  341.  
  342. HRESULT _IFUNC
  343. TTypeLibrary::QueryInterface(const IID far& riid, void far* far* retIface)
  344. {
  345.   if (riid == IID_IUnknown || riid == IID_ITypeLib) {
  346.     AddRef();
  347.     *retIface = (IUnknown*)this;
  348.     return HR_NOERROR;
  349.   }
  350.   *retIface = 0;
  351.   return HR_NOINTERFACE;
  352. }
  353.  
  354. unsigned long _IFUNC
  355.  
  356. TTypeLibrary::AddRef()
  357. {
  358.   return ++RefCnt;
  359. }
  360.  
  361. unsigned long _IFUNC
  362. TTypeLibrary::Release()
  363. {
  364.   if (--RefCnt != 0)
  365.     return RefCnt;
  366.   delete this;
  367.   return 0;
  368. }
  369.  
  370. unsigned int _IFUNC
  371. TTypeLibrary::GetTypeInfoCount()
  372. {
  373.   return AppDesc.GetClassCount() + (CoClassImplCount > 0);  // +1 for CoClass
  374. }
  375.  
  376. HRESULT _IFUNC
  377. TTypeLibrary::GetTypeInfo(unsigned index, ITypeInfo* far* retInfo)
  378. {
  379.   if (CoClassImplCount > 0 && index == AppDesc.GetClassCount()) {
  380.     *retInfo = CreateCoClassInfo();
  381.   } else {
  382.     TAutoClass* cls = AppDesc.GetAutoClass(index);
  383.     if (!cls)
  384.       return HR_TYPE_ELEMENTNOTFOUND;
  385.     *retInfo = AppDesc.CreateITypeInfo(*cls);
  386.   }
  387.   return HR_NOERROR;
  388. }
  389.  
  390. HRESULT _IFUNC
  391. TTypeLibrary::GetTypeInfoType(unsigned index, TYPEKIND far* retKind)
  392. {
  393.   unsigned int count = AppDesc.GetClassCount();
  394.   if (index > count)
  395.     return HR_TYPE_ELEMENTNOTFOUND;
  396.   *retKind = (index == count ? TKIND_COCLASS : TKIND_DISPATCH);
  397.   return HR_NOERROR;
  398. }
  399.  
  400. HRESULT _IFUNC
  401. TTypeLibrary::GetTypeInfoOfGuid(const GUID far& guid, ITypeInfo* far* retInfo)
  402. {
  403.   if (AppDesc.AppClassId.GetOffset(guid) == 0) {
  404.     *retInfo = CreateCoClassInfo();
  405.   } else {
  406.     TAutoClass* cls = AppDesc.GetAutoClass(guid);
  407.     if (!cls)
  408.       return HR_TYPE_ELEMENTNOTFOUND;
  409.     *retInfo = AppDesc.CreateITypeInfo(*cls);
  410.   }
  411.   return HR_NOERROR;
  412. }
  413.  
  414. HRESULT _IFUNC
  415. TTypeLibrary::GetLibAttr(TLIBATTR far* far* retAttr)
  416. {
  417.   TLIBATTR* libAttr = new TLIBATTR;
  418.   memset(libAttr, 0, sizeof(TLIBATTR));
  419. #if defined(BI_PLAT_WIN32)
  420.   libAttr->syskind = SYS_WIN32;
  421. #elif defined(BI_PLAT_WIN16)
  422.   libAttr->syskind = SYS_WIN16;
  423. #endif
  424.   libAttr->lcid = Lang;
  425.   AppDesc.GetClassId(0, libAttr->guid);
  426.   libAttr->wMajorVerNum = AppDesc.GetVersionField(0);
  427.   libAttr->wMinorVerNum = AppDesc.GetVersionField(1);
  428.   *retAttr = libAttr;
  429.   return HR_NOERROR;
  430. }
  431.  
  432. void _IFUNC
  433. TTypeLibrary::ReleaseTLibAttr(TLIBATTR far* attr)
  434. {
  435.   delete attr;
  436. }
  437.  
  438. HRESULT _IFUNC
  439. TTypeLibrary::GetTypeComp(ITypeComp* far* /*retComp*/)
  440. {
  441.   return HR_TYPE_UNSUPFORMAT;
  442. }
  443.  
  444. HRESULT _IFUNC
  445. TTypeLibrary::GetDocumentation(int index, BSTR far* retName,
  446.                                BSTR far* retDoc,
  447.                                ulong far* retHelpContext,
  448.                                BSTR far* retHelpFile)
  449. {
  450.   if (retHelpFile)
  451.      *retHelpFile = NS_CLASSLIB::SysAllocString(AppDesc.GetHelpFile(Lang));
  452.   if (retHelpContext)
  453.      *retHelpContext = 0;
  454.   if (index == -1 || index == AppDesc.GetClassCount()) { // library itself
  455.     if (retName)
  456.       *retName = NS_CLASSLIB::SysAllocString(AppDesc.GetAppName(Lang));
  457.     if (retDoc)
  458.       *retDoc  = NS_CLASSLIB::SysAllocString(AppDesc.GetAppDoc(Lang));
  459.     if (retHelpContext)
  460.       *retHelpContext = 0;
  461.   } else {
  462.     TAutoClass* cls = AppDesc.GetAutoClass(index);
  463.     if (!cls)
  464.       return HR_TYPE_ELEMENTNOTFOUND;
  465.     if (retName)
  466.       *retName = NS_CLASSLIB::SysAllocString(cls->GetName(Lang));
  467.     if (retDoc)
  468.       *retDoc  = NS_CLASSLIB::SysAllocString(cls->GetDoc(Lang));
  469.     if (retHelpContext)
  470.       *retHelpContext = cls->GetHelpId();
  471.   }
  472.   return HR_NOERROR;
  473. }
  474.  
  475. HRESULT _IFUNC
  476. TTypeLibrary::IsName(OLECHAR far* nameBuf, ulong /*hashVal*/, int far* retFound)
  477. {
  478.   TAutoClass::TAutoClassRef* ref = AppDesc.ClassList;
  479.   for (int index = 0; index < AppDesc.ClassCount; index++, ref++) {
  480.     TAutoClass* cls = ref->Class;
  481.     // not clear from doc if we should check names of classes as well as members
  482.     long id;
  483.     TAutoSymbol* sym = cls->Lookup(OleStr(nameBuf), Lang, asOleType, id);
  484.     if (sym) {
  485. #if defined(BI_OLECHAR_WIDE)
  486.       lstrcpyW(nameBuf, OleStr(sym->Name));
  487. #else
  488.       strcpy(nameBuf, sym->Name);
  489. #endif
  490.       *retFound = 1;
  491.       return HR_NOERROR;
  492.     }
  493.   }
  494.   return ResultFromScode(TYPE_E_ELEMENTNOTFOUND);
  495. }
  496.  
  497. HRESULT _IFUNC
  498. TTypeLibrary::FindName(OLECHAR far* nameBuf, ulong /*lHashVal*/,
  499.                        ITypeInfo* far* retInfo, MEMBERID far* retId,
  500.                        unsigned short far* inoutCount)
  501. {
  502.   unsigned short found = 0;
  503.   TAutoClass::TAutoClassRef* ref = AppDesc.ClassList;
  504.   for (int index = 0; index < AppDesc.ClassCount && found < *inoutCount;
  505.                       index++, ref++) {
  506.     TAutoClass* cls = ref->Class;
  507.     long id;
  508.     TAutoSymbol* sym = cls->Lookup(OleStr(nameBuf), Lang, asOleType, id);
  509.     if (sym) {
  510.       retId[found] = id;
  511.       retInfo[found] = AppDesc.CreateITypeInfo(*cls);
  512.       found++;
  513.     }
  514.   }
  515.   *inoutCount = found;
  516.   return found ? HR_NOERROR : HR_TYPE_ELEMENTNOTFOUND;
  517. }
  518.  
  519. //____________________________________________________________________________
  520. //
  521. // TCoClassInfo implementation
  522. //____________________________________________________________________________
  523.  
  524. TCoClassInfo::TCoClassInfo(TAppDescriptor& appDesc, uint16 typeFlags, int implCount)
  525. : AppDesc(appDesc), RefCnt(0), TypeFlags(typeFlags), ImplCount(implCount)
  526. {
  527.   ImplList = new unsigned[implCount];
  528.   TAutoClass::TAutoClassRef* ref = AppDesc.ClassList;
  529.   int iapp     = -1;
  530.   int ievent   = -1;
  531.   Default      = -1;
  532.   DefaultEvent = -1;
  533.   int iclass   =  0;
  534.   for (int index = 0; iclass < implCount; index++, ref++) {
  535.     TAutoClass* cls = ref->Class;
  536.     int    implFlags = cls->GetImplTypeFlags();
  537.     uint16 typeFlags = cls->GetCoClassFlags();
  538.     if (implFlags || typeFlags) {
  539.       if (implFlags & IMPLTYPEFLAG_FSOURCE) {
  540.         ievent = iclass;
  541.         if (implFlags & IMPLTYPEFLAG_FDEFAULT)
  542.           DefaultEvent = iclass;
  543.       } else {
  544.         if (typeFlags & TYPEFLAG_FAPPOBJECT)
  545.           iapp = iclass;
  546.         if (implFlags & IMPLTYPEFLAG_FDEFAULT)
  547.           Default = iclass;
  548.       }
  549.       ImplList[iclass++] = index;
  550.     }
  551.   }
  552.   if (Default == -1)
  553.     Default = iapp;
  554.   if (DefaultEvent == -1)
  555.     DefaultEvent = ievent;
  556. }
  557.  
  558. TCoClassInfo::~TCoClassInfo()
  559. {
  560.   delete ImplList;
  561. }
  562.  
  563. HRESULT _IFUNC
  564. TCoClassInfo::QueryInterface(const IID far& riid, void far* far* retIface)
  565. {
  566.   if (riid == IID_IUnknown || riid == IID_ITypeInfo) {
  567.     AddRef();
  568.     *retIface = (IUnknown*)this;
  569.     return HR_NOERROR;
  570.   }
  571.   *retIface = 0;
  572.   return HR_NOINTERFACE;
  573. }
  574.  
  575. unsigned long _IFUNC
  576.  
  577. TCoClassInfo::AddRef()
  578. {
  579.   return ++RefCnt;
  580. }
  581.  
  582. unsigned long _IFUNC
  583. TCoClassInfo::Release()
  584. {
  585.   if (--RefCnt != 0)
  586.     return RefCnt;
  587.   delete this;
  588.   return 0;
  589. }
  590.  
  591. HRESULT _IFUNC
  592. TCoClassInfo::GetTypeAttr(TYPEATTR far* far* retTypeAttr)
  593. {
  594.   TYPEATTR* ta = (TYPEATTR*)new char[sizeof(TYPEATTR)];
  595.   memset(ta, 0, sizeof(TYPEATTR));
  596.   ta->guid = AppDesc.AppClassId;
  597.   ta->lcid = AppDesc.GetAppLang();
  598.   ta->typekind = TKIND_COCLASS;
  599.   ta->cImplTypes = (unsigned short)ImplCount;
  600.   ta->wMajorVerNum = AppDesc.GetVersionField(0);
  601.   ta->wMinorVerNum = AppDesc.GetVersionField(1);
  602.   ta->wTypeFlags = TypeFlags;
  603.   *retTypeAttr = ta;
  604.   return HR_NOERROR;
  605. }
  606.  
  607. void _IFUNC
  608. TCoClassInfo::ReleaseTypeAttr(TYPEATTR far* ptypeattr)
  609. {
  610.   delete [] (char*)ptypeattr;
  611. }
  612.  
  613. HRESULT _IFUNC
  614. TCoClassInfo::GetDocumentation(MEMBERID memid,
  615.                                 BSTR far* retName, BSTR far* retDoc,
  616.                                 ulong far* retHelpContext,
  617.                                 BSTR far* retHelpFile)
  618. {
  619.   if (retHelpFile)
  620.     *retHelpFile = NS_CLASSLIB::SysAllocString(AppDesc.GetHelpFile(AppDesc.GetAppLang()));
  621.   if (memid == -1) {       // request info on type library itself
  622.     if (retName)
  623.       *retName = NS_CLASSLIB::SysAllocString(AppDesc.GetAppName(AppDesc.GetAppLang()));
  624.     if (retDoc)
  625.       *retDoc  = NS_CLASSLIB::SysAllocString(AppDesc.GetAppDoc(AppDesc.GetAppLang()));
  626.     if (retHelpContext)
  627.       *retHelpContext = 0;
  628.   } else {
  629.     return HR_TYPE_WRONGTYPEKIND;
  630.   }
  631.   return HR_NOERROR;
  632. }
  633.  
  634. HRESULT _IFUNC
  635. TCoClassInfo::CreateInstance(IUnknown* /*punkOuter*/, const IID far& /*riid*/,
  636.                               void far* far* /*ppvObj*/)
  637. {
  638.   return HR_TYPE_WRONGTYPEKIND;
  639. }
  640.  
  641. HRESULT _IFUNC
  642. TCoClassInfo::GetContainingTypeLib(ITypeLib* far* retLib,
  643.                                                 unsigned int far* retIndex)
  644. {
  645.   *retLib = AppDesc.GetTypeLibrary();
  646.   if (retIndex)
  647.     *retIndex = AppDesc.GetClassCount();
  648.   return HR_NOERROR;
  649. }
  650.  
  651. HRESULT _IFUNC
  652. TCoClassInfo::GetRefTypeInfo(HREFTYPE hreftype, ITypeInfo* far* retInfo)
  653. {
  654.   TAutoClass* cls = (TAutoClass*)hreftype;
  655.   if (AppDesc.GetClassIndex(cls) == -1)  // validate pointer to avoid crash
  656.     return HR_TYPE_WRONGTYPEKIND;
  657.   *retInfo = AppDesc.CreateITypeInfo(*cls);
  658.   return HR_NOERROR;
  659. }
  660.  
  661. HRESULT _IFUNC
  662. TCoClassInfo::GetImplTypeFlags(unsigned int index, int far* retflags)
  663. {
  664.   TAutoClass* cls = index<ImplCount ? AppDesc.GetAutoClass(ImplList[index]):0;
  665.   if (!cls)
  666.     return HR_TYPE_ELEMENTNOTFOUND;
  667.   int implFlags = cls->GetImplTypeFlags();
  668.   if (implFlags & IMPLTYPEFLAG_FSOURCE) {
  669.     if (index == DefaultEvent)
  670.       implFlags |= IMPLTYPEFLAG_FDEFAULT;
  671.   } else {
  672.     if (index == Default)
  673.       implFlags |= IMPLTYPEFLAG_FDEFAULT;
  674.   }
  675.   *retflags = implFlags;
  676.   return HR_NOERROR;
  677. }
  678.  
  679. HRESULT _IFUNC
  680. TCoClassInfo::GetRefTypeOfImplType(unsigned int index,
  681.                                     HREFTYPE far* retreftype)
  682. {
  683.   TAutoClass* cls = index<ImplCount ? AppDesc.GetAutoClass(ImplList[index]):0;
  684.   *retreftype = (HREFTYPE)cls;
  685.   return cls ? HR_NOERROR : HR_TYPE_ELEMENTNOTFOUND;
  686. }
  687.  
  688. // The following methods of ITypeInfo are not relevant for a COCLASS typeinfo
  689.  
  690. HRESULT _IFUNC
  691. TCoClassInfo::GetFuncDesc(unsigned int, FUNCDESC far* far*)
  692. {
  693.   return HR_TYPE_WRONGTYPEKIND;
  694. }
  695.  
  696. void _IFUNC
  697. TCoClassInfo::ReleaseFuncDesc(FUNCDESC far*)
  698. {
  699. }
  700.  
  701. HRESULT _IFUNC
  702. TCoClassInfo::GetVarDesc(unsigned int, VARDESC far* far*)
  703. {
  704.   return HR_TYPE_WRONGTYPEKIND;
  705. }
  706.  
  707. void _IFUNC
  708. TCoClassInfo::ReleaseVarDesc(VARDESC far*)
  709. {
  710. }
  711.  
  712. HRESULT _IFUNC
  713. TCoClassInfo::GetNames(MEMBERID, BSTR far*, unsigned int, unsigned int far*)
  714. {
  715.   return HR_TYPE_WRONGTYPEKIND;
  716. }
  717.  
  718. HRESULT _IFUNC
  719. TCoClassInfo::GetIDsOfNames(OLECHAR far* far*, uint, MEMBERID far*)
  720. {
  721.   return HR_TYPE_WRONGTYPEKIND;
  722. }
  723.  
  724. HRESULT _IFUNC
  725. TCoClassInfo::Invoke(void far*, MEMBERID, unsigned short, DISPPARAMS far*,
  726.                       VARIANT far*, EXCEPINFO far*, unsigned int far*)
  727. {
  728.   return HR_TYPE_WRONGTYPEKIND;
  729. }
  730.  
  731. HRESULT _IFUNC
  732. TCoClassInfo::GetTypeComp(ITypeComp* far*)
  733. {
  734.   return HR_TYPE_LIBNOTREGISTERED;
  735. }
  736.  
  737. HRESULT _IFUNC
  738. TCoClassInfo::GetMops(MEMBERID, BSTR far*)
  739. {
  740.   return HR_TYPE_WRONGTYPEKIND;
  741. }
  742.  
  743. HRESULT _IFUNC
  744. TCoClassInfo::GetDllEntry(MEMBERID, INVOKEKIND, BSTR far*, BSTR far*,
  745.                           unsigned short far*)
  746. {
  747.   return HR_TYPE_WRONGTYPEKIND;
  748. }
  749.  
  750. HRESULT _IFUNC
  751. TCoClassInfo::AddressOfMember(MEMBERID, INVOKEKIND, void far* far*)
  752. {
  753.   return HR_TYPE_WRONGTYPEKIND;
  754. }
  755.  
  756.